/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.sunsg.okhttptest.bean;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
import android.provider.MediaStore.Images.ImageColumns;
import android.util.Log;

import com.example.sunsg.okhttptest.util.BitmapManager;

import java.io.Closeable;
import java.io.FileNotFoundException;
import java.io.IOException;

/**
 * The class for normal images in gallery.
 */
public class Image implements Parcelable {
	
	private static final String TAG = "Image";
	private static final int UNKNOWN_LENGTH = -1;
	protected ImageList mContainer;
	public ImageList getmContainer() {
		return mContainer;
	}

	public void setmContainer(ImageList mContainer) {
		this.mContainer = mContainer;
	}

	public ContentResolver getmContentResolver() {
		return mContentResolver;
	}

	public void setmContentResolver(ContentResolver mContentResolver) {
		this.mContentResolver = mContentResolver;
	}

	public Uri getmUri() {
		return mUri;
	}

	public void setmUri(Uri mUri) {
		this.mUri = mUri;
	}

	public long getmId() {
		return mId;
	}

	public void setmId(long mId) {
		this.mId = mId;
	}

	public String getmDataPath() {
		return mDataPath;
	}

	public void setmDataPath(String mDataPath) {
		this.mDataPath = mDataPath;
	}

	public int getmIndex() {
		return mIndex;
	}

	public void setmIndex(int mIndex) {
		this.mIndex = mIndex;
	}

	public String getmMimeType() {
		return mMimeType;
	}

	public void setmMimeType(String mMimeType) {
		this.mMimeType = mMimeType;
	}

	public long getmDateTaken() {
		return mDateTaken;
	}

	public void setmDateTaken(long mDateTaken) {
		this.mDateTaken = mDateTaken;
	}

	public String getmTitle() {
		return mTitle;
	}

	public void setmTitle(String mTitle) {
		this.mTitle = mTitle;
	}

	public double getLatitude() {
		return latitude;
	}

	public void setLatitude(double latitude) {
		this.latitude = latitude;
	}

	public double getLongitude() {
		return longitude;
	}

	public void setLongitude(double longitude) {
		this.longitude = longitude;
	}

	public ExifInterface getmExif() {
		return mExif;
	}

	public void setmExif(ExifInterface mExif) {
		this.mExif = mExif;
	}

	public int getmRotation() {
		return mRotation;
	}

	public void setmRotation(int mRotation) {
		this.mRotation = mRotation;
	}

	public Bitmap getBitmap() {
		return bitmap;
	}

	public void setBitmap(Bitmap bitmap) {
		this.bitmap = bitmap;
	}

	public int getmWidth() {
		return mWidth;
	}

	public void setmWidth(int mWidth) {
		this.mWidth = mWidth;
	}

	public int getmHeight() {
		return mHeight;
	}

	public void setmHeight(int mHeight) {
		this.mHeight = mHeight;
	}

	public static String getTag() {
		return TAG;
	}

	public static int getUnknownLength() {
		return UNKNOWN_LENGTH;
	}

	public static Parcelable.Creator<Image> getCreator() {
		return CREATOR;
	}

	protected ContentResolver mContentResolver;
	public Uri mUri;
	public long mId;
	public String mDataPath;
	public int mIndex;
	public String mMimeType;
	public long mDateTaken = -1;
	public String mTitle;
	public double latitude;
	public double longitude;
	public ExifInterface mExif;

	public int mRotation;
	public Bitmap bitmap;
	private int mWidth = UNKNOWN_LENGTH;
	private int mHeight = UNKNOWN_LENGTH;

	public Image(ImageList container, ContentResolver cr, long id,
				 int index, Uri uri, String dataPath, String mimeType,
				 long dateTaken, String title, int rotation, double latitude,
				 double longitude) {
		this.mContainer = container;
		this.mContentResolver = cr;
		this.mId = id;
		this.mIndex = index;
		this.mUri = uri;
		this.mDataPath = dataPath;
		this.mMimeType = mimeType;

		this.mTitle = title;
		this.mRotation = rotation;
		this.latitude = latitude;
		this.longitude = longitude;
		this.mDateTaken = dateTaken;
	}
	public Image(){}

	public Image(Parcel in) {
		mId = in.readLong();
		mDateTaken = in.readLong();
		latitude = in.readDouble();
		longitude = in.readDouble();
		mUri= in.readParcelable(null);
		mRotation = in.readInt();
		mDataPath = in.readString();
		mWidth = in.readInt();
		mHeight = in.readInt();
	}

	public int getDegreesRotated() {
		return mRotation;
	}

	protected void setDegreesRotated(int degrees) {
		if (mRotation == degrees)
			return;
		mRotation = degrees;
		ContentValues values = new ContentValues();
		values.put(ImageColumns.ORIENTATION, mRotation);
		mContentResolver.update(mUri, values, null, null);
	}

	public boolean isReadonly() {
		String mimeType = getMimeType();
		return !"image/jpeg".equals(mimeType) && !"image/png".equals(mimeType);
	}

	public boolean isDrm() {
		return false;
	}

	/**
	 * Replaces the tag if already there. Otherwise, adds to the exif tags.
	 *
	 * @param tag
	 * @param value
	 */
	public void replaceExifTag(String tag, String value) {
		if (mExif == null) {
			loadExifData();
		}
		mExif.setAttribute(tag, value);
	}

	private void loadExifData() {
		try {
			mExif = new ExifInterface(mDataPath);
		} catch (IOException ex) {
			Log.e(TAG, "cannot read exif", ex);
		}
	}

	private void saveExifData() throws IOException {
		if (mExif != null) {
			mExif.saveAttributes();
		}
	}

	private void setExifRotation(int degrees) {
		try {
			degrees %= 360;
			if (degrees < 0)
				degrees += 360;

			int orientation = ExifInterface.ORIENTATION_NORMAL;
			switch (degrees) {
			case 0:
				orientation = ExifInterface.ORIENTATION_NORMAL;
				break;
			case 90:
				orientation = ExifInterface.ORIENTATION_ROTATE_90;
				break;
			case 180:
				orientation = ExifInterface.ORIENTATION_ROTATE_180;
				break;
			case 270:
				orientation = ExifInterface.ORIENTATION_ROTATE_270;
				break;
			}

			replaceExifTag(ExifInterface.TAG_ORIENTATION,
					Integer.toString(orientation));
			saveExifData();
		} catch (Exception ex) {

		}
	}

	/**
	 * Save the rotated image by updating the Exif "Orientation" tag.
	 *
	 * @param degrees
	 */
	public boolean rotateImageBy(int degrees) {
		int newDegrees = (getDegreesRotated() + degrees) % 360;
		setExifRotation(newDegrees);
		setDegreesRotated(newDegrees);
		return true;
	}

	public String getDataPath() {
		return mDataPath;
	}

	@Override
	public boolean equals(Object other) {
		if (other == null || !(other instanceof Image))
			return false;
		return mUri.equals(((Image) other).mUri);
	}

	@Override
	public int hashCode() {
		return mUri.hashCode();
	}

	public ImageList getContainer() {
		return mContainer;
	}

	public long getDateTaken() {
		return mDateTaken;
	}

	public String getMimeType() {
		return mMimeType;
	}

	public String getTitle() {
		return mTitle;
	}

	public void setupDimension() {
		ParcelFileDescriptor input = null;
		try {
			input = mContentResolver.openFileDescriptor(mUri, "r");
			BitmapFactory.Options options = new BitmapFactory.Options();
			options.inJustDecodeBounds = true;
			BitmapManager.instance().decodeFileDescriptor(
					input.getFileDescriptor(), options);
			mWidth = options.outWidth;
			mHeight = options.outHeight;
		} catch (FileNotFoundException ex) {
			mWidth = 0;
			mHeight = 0;
		} finally {
			closeSilently(input);
		}
	}

	public int getWidth() {
		if (mWidth == UNKNOWN_LENGTH)
			setupDimension();
		return mWidth;
	}

	public int getHeight() {
		if (mHeight == UNKNOWN_LENGTH)
			setupDimension();
		return mHeight;
	}

	@Override
	public String toString() {
		return mUri.toString();
	}

	public void closeSilently(Closeable c) {
		if (c == null)
			return;
		try {
			c.close();
		} catch (Throwable t) {
			// do nothing
		}
	}

	@Override
	public int describeContents() {

		return 0;
	}

	@Override
	public void writeToParcel(Parcel dest, int flags) {
		dest.writeLong(mId);
		dest.writeLong(mDateTaken);
		dest.writeDouble(latitude);
		dest.writeDouble(longitude);
		dest.writeParcelable(mUri, PARCELABLE_WRITE_RETURN_VALUE);
		dest.writeInt(mRotation);
		dest.writeString(mDataPath);
		dest.writeInt(mWidth);
		dest.writeInt(mHeight);
	}

	public static final Parcelable.Creator<Image> CREATOR = new Creator<Image>() {
		public Image createFromParcel(Parcel source) {
			return new Image(source);
		}

		public Image[] newArray(int size) {
			return new Image[size];
		}
	};

}
